package com.gomyb.job.utils;

import com.gomyb.job.constant.Constant;
import com.gomyb.job.model.ScheduleJobEntity;
import com.gomyb.job.task.Task;
import com.gomyb.utils.BeanUtil;
import com.gomyb.web.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

/**
 * @author <a href="mailto:hellohesir@gmail.com">Mr_He</a>
 * 2019/6/19 15:42
 * <p>
 * 任务执行器
 */
@Slf4j
public class ScheduleJob extends QuartzJobBean {

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        ScheduleJobEntity job = (ScheduleJobEntity) context.getMergedJobDataMap().get(Constant.JOB_KEY);
        try {
            long begin = System.currentTimeMillis();
            Object bean = SpringContextUtil.getBean(job.getBeanName());
            AnnotatedType[] annotatedInterfaces = bean.getClass().getAnnotatedInterfaces();
            for (AnnotatedType annotatedInterface : annotatedInterfaces) {
                Type sType = annotatedInterface.getType();
                if (sType instanceof Class) {
                    Method method = bean.getClass().getMethod("run", Object.class);
                    Object o = BeanUtil.byteArrayToObject(job.getParam());
                    method.invoke(bean, o);
                    break;
                } else if (sType instanceof ParameterizedTypeImpl) {
                    ParameterizedTypeImpl type = (ParameterizedTypeImpl) annotatedInterface.getType();
                    String typeName;
                    if (!(type.getActualTypeArguments()[0]).getClass().equals(ParameterizedTypeImpl.class)) {
                        Type type1 = type.getActualTypeArguments()[0];
                        typeName = type1.getTypeName();
                    } else {
                        ParameterizedTypeImpl type1 = ((ParameterizedTypeImpl) type.getActualTypeArguments()[0]);
                        typeName = type1.getRawType().getTypeName();
                    }
                    Class<?> aClass = Class.forName(typeName);
                    Class<?> aClass1 = Class.forName(type.getRawType().getName());
                    Method method = bean.getClass().getMethod("run", aClass);
                    if (aClass1.equals(Task.class)) {
                        Object o = BeanUtil.byteArrayToObject(job.getParam());
                        method.invoke(bean, o);
                        break;
                    }
                }
            }
            long end = System.currentTimeMillis();
            log.info("定时器执行成功：[{}]", end - begin);
        } catch (Exception e) {
            log.info("定时器执行失败", e);
        }
    }
}
